(define (accumulate op initial sequence)
    (if (null? sequence)
        initial
        (op 
            (car sequence)
            (accumulate op initial (cdr sequence))
        )
    )
)
(define (accumulate-n op init  seqs)
    (if (null? (car seqs))
        `()
        (cons 
            (accumulate 
                op 
                init 
                (map
                    (lambda (items) (car items)) 
                    seqs
                )
            )
            (accumulate-n 
                op 
                init 
                (map
                    (lambda (items) (cdr items)) 
                    seqs
                )
            )
        )
    )
)

(define v (list 1 2 3 4))
(define m
    (list 
        (list 1 2 3 4)
        (list 4 5 6 6)
        (list 6 7 8 9)
        (list 6 7 8 9)
    )
)
(define (dot-product v w)
    (accumulate + 0 (map * v w))
)
(display (dot-product v v))
(newline)

(define (matrix-*-vector m v1)
    (map 
        (lambda (m-item)
            (dot-product m-item v1) 
        ) 
        m        
    )
)
(display (matrix-*-vector m v))
(newline)

(define (transpose mat)
    (accumulate-n
        (lambda (v2 m2) 
            (append (list v2) m2 )
        )
        `() 
        mat
    )
)
(display (transpose m))
(newline)

(define (matrix-*-matrix m n)
    (let 
        ( (cols (transpose n)))    
        (map 
            (lambda (m-item) 
                (matrix-*-vector cols m-item)
            )
            m
        )
    )    
)
(display (matrix-*-matrix m m))
(exit)